package com.focus.pay.wx.action.v2;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.BeanCopier;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.XmlUtil;
import com.focus.pay.wx.config.WxPayConfig;
import com.focus.pay.wx.constant.WxPayConstant;
import com.focus.pay.core.exception.PayException;
import com.focus.pay.core.pay.*;
import com.focus.pay.core.utils.HttpClientUtils;
import com.focus.pay.wx.model.order.v2.WxPayCommon;
import com.focus.pay.wx.model.order.v2.WxPayModelQuery;
import com.focus.pay.wx.model.order.v2.WxPayModelQueryResponse;
import com.focus.pay.wx.model.cancel.v2.WxPayModelCancel;
import com.focus.pay.wx.model.cancel.v2.WxPayModelCancelResponse;
import com.focus.pay.wx.model.download.v2.WxPayModelTradeDownload;
import com.focus.pay.wx.model.refund.v2.WxPayModelRefund;
import com.focus.pay.wx.model.refund.v2.WxPayModelRefundQuery;
import com.focus.pay.wx.model.refund.v2.WxPayModelRefundQueryResponse;
import com.focus.pay.wx.model.refund.v2.WxPayModelRefundResponse;
import com.focus.pay.wx.utils.WxPayUtils;

import java.util.HashMap;
import java.util.Map;

/**
* @Author: 赵参谋
* @Date: 2021/10/12 11:25
* @Description: 微信支付V2
 * 1 微信支付结果查询
 * 2 微信支付撤销交易
 * 3 微信支付申请退款
 * 4 微信支付退款查询
 * 5 微信支付账单下载
*/
public class WxPayOrder implements
        PayQueryInterface<WxPayModelQueryResponse, WxPayModelQuery, WxPayConfig>,
        PayCloseInterface<WxPayModelCancelResponse, WxPayModelCancel,WxPayConfig>,
        PayRefundInterface<com.focus.pay.wx.model.refund.v2.WxPayModelRefundResponse, com.focus.pay.wx.model.refund.v2.WxPayModelRefund,WxPayConfig>,
        PayRefundQueryInterface<com.focus.pay.wx.model.refund.v2.WxPayModelRefundQueryResponse, com.focus.pay.wx.model.refund.v2.WxPayModelRefundQuery,WxPayConfig>,
        PayTradeDownlaodInterface<String, com.focus.pay.wx.model.download.v2.WxPayModelTradeDownload,WxPayConfig> {

    /**
     * 支付结果查询
     * @param wxPayModelQuery 微信查询参数
     * @param wxPayConfig 微信配置参数
     * @return 支付结果
     * @throws PayException
     */
    @Override
    public WxPayModelQueryResponse payQuery(WxPayModelQuery wxPayModelQuery, WxPayConfig wxPayConfig) throws PayException {
        String res = HttpClientUtils.doPost(
                this.buildRequestPath(WxPayConstant.WxPayPathV2.QUERY_ORDER),
                this.buildRequestParam(wxPayModelQuery,wxPayConfig));
        return this.resolvingResult(res, WxPayModelQueryResponse.class);

    }

    /**
     * 撤销订单
     * @param wxPayModelCancel 撤销订单参数
     * @param wxPayConfig 微信配置参数
     * @return 撤销结果
     * @throws PayException
     */
    @Override
    public com.focus.pay.wx.model.cancel.v2.WxPayModelCancelResponse payClose(WxPayModelCancel wxPayModelCancel, WxPayConfig wxPayConfig) throws PayException {
        String res = HttpClientUtils.doPost(
                this.buildRequestPath(WxPayConstant.WxPayPathV2.CANCEL_ORDER),
                this.buildRequestParam(wxPayModelCancel, wxPayConfig),
                WxPayUtils.buildSSLFactory(wxPayConfig));
        return this.resolvingResult(res, WxPayModelCancelResponse.class);

    }

    /**
     * 退款订单
     * @param wxPayModelRefund 退款单信息
     * @param wxPayConfig 配置参数
     * @return 撤销结果
     * @throws PayException
     */
    @Override
    public com.focus.pay.wx.model.refund.v2.WxPayModelRefundResponse payRefund(WxPayModelRefund wxPayModelRefund, WxPayConfig wxPayConfig) throws PayException {
            HashMap<String,String> map = BeanCopier.create(wxPayModelRefund,new HashMap<String,String>(), CopyOptions.create().ignoreNullValue()).copy();
            String res =HttpClientUtils.doPost(
                    this.buildRequestPath(WxPayConstant.WxPayPathV2.REFUND_ORDER),
                    this.buildRequestParam(wxPayModelRefund,wxPayConfig),
                    WxPayUtils.buildSSLFactory(wxPayConfig));
            return this.resolvingResult(res, WxPayModelRefundResponse.class);

    }

    /**
     * 微信退款查询
     * @param wxPayModelRefundQuery 退款单查询参数
     * @param wxPayConfig 配置参数
     * @return 退款查询结果
     * @throws PayException
     */
    @Override
    public com.focus.pay.wx.model.refund.v2.WxPayModelRefundQueryResponse payRefundQuery(WxPayModelRefundQuery wxPayModelRefundQuery, WxPayConfig wxPayConfig) throws PayException {
        String res = HttpClientUtils.doPost(
                    this.buildRequestPath(WxPayConstant.WxPayPathV2.REFUND_QUERY),
                    this.buildRequestParam(wxPayModelRefundQuery,wxPayConfig));
        return this.resolvingResult(res, WxPayModelRefundQueryResponse.class);

    }

    /**
     * 账单下载
     * @param wxPayModelTradeDownload 账单下载参数
     * @param wxPayConfig 配置参数
     * @return 自行处理返回字数据
     * @throws PayException
     */
    @Override
    public String tradeDownload(WxPayModelTradeDownload wxPayModelTradeDownload, WxPayConfig wxPayConfig) throws PayException {
        String res = HttpClientUtils.doPost(
                    this.buildRequestPath(WxPayConstant.WxPayPathV2.TRADE_DOWNLOAD),
                    this.buildRequestParam(wxPayModelTradeDownload,wxPayConfig));
        return res;

    }

    /**
     * 构建请求参数
     * @return xml请求参数
     */
    protected <T extends WxPayCommon> String buildRequestParam(T t, WxPayConfig wxPayConfig) throws PayException {
        return t.buildParam(t,wxPayConfig).buildRequestParam(t);
    }

    /**
     * 构建请求路径
     * @return 请求路径
     */
    protected String buildRequestPath(WxPayConstant.WxPayPathV2 wxPayPathV2){
        return WxPayConstant.WxPayPathV2.buildRequestPath(wxPayPathV2);
    }

    /**
     * 解析结果
     * XML转BEAN
     * @param result 请求返回字符串
     * @param <T> 实体类
     * @return 实体类
     */
    protected  <T> T resolvingResult(String result,Class<T> t){
        Map<String,Object> map = XmlUtil.xmlToMap(result);
        T bean =  BeanUtil.mapToBean(map,t,false);
        //验签TODO
        return bean;
    }


}
